﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using QSHC.LibrarySL.MVVM;
using QSHC.QSchedule.Web.Services;
using System.Collections.Generic;
using QSHC.QSchedule.Web.Models;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using QSHC.QSchedule.Silverlight.Helpers;
using QSHC.QSchedule.Silverlight.Views;
using QSHC.LibrarySL.Ria;
using System.Windows.Browser;

namespace QSHC.QSchedule.Silverlight.ViewModels
{
    public class AppointmentListViewModel : ViewModelBase
    {
        private QScheduleDomainContext _dc = new QScheduleDomainContext();

        #region Properties
        
        //Daeng
        #region CanDeleteAppointment
        private bool _canDeleteAppointment;
        public bool CanDeleteAppointment
        {
            get { return _canDeleteAppointment; }
            set
            {
                if (_canDeleteAppointment != value)
                {
                    _canDeleteAppointment = value;
                    OnPropertyChanged(() => CanDeleteAppointment);

                    DeleteCommand.OnCanExecuteChanged();
                }
            }
        }
        #endregion

        #region Property Appointments
        private IEnumerable<Appointment> _appointments;
        public IEnumerable<Appointment> Appointments
        {
            get { return _appointments; }
            set
            {
                if (_appointments != value)
                {
                    _appointments = value;
                    OnPropertyChanged(() => Appointments);
                }
            }
        }
        #endregion

        #region Property SelectedAppointment
        private Appointment _appointment;
        public Appointment SelectedAppointment
        {
            get { return _appointment; }
            set
            {
                if (_appointment != value)
                {
                    _appointment = value;
                    OnPropertyChanged(() => SelectedAppointment);
                }
            }
        }
        #endregion

        #region Property BeginDate
        private DateTime _beginDate;
        public DateTime BeginDate
        {
            get { return _beginDate; }
            set
            {
                if (_beginDate != value)
                {
                    _beginDate = value;
                    OnPropertyChanged(() => BeginDate);
                }
            }
        }
        #endregion

        #region Property EndDate
        private DateTime? _endDate;
        public DateTime? EndDate
        {
            get { return _endDate; }
            set
            {
                if (_endDate != value)
                {
                    _endDate = value;
                    OnPropertyChanged(() => EndDate);
                }
            }
        }
        #endregion

        #region Property ServiceID
        private int? _serviceID;
        public int? ServiceID
        {
            get { return _serviceID; }
            set
            {
                if (_serviceID != value)
                {
                    _serviceID = value;
                    OnPropertyChanged(() => ServiceID);
                }
            }
        }

        #endregion

        #region Property Services
        private IEnumerable<Service> _services;
        public IEnumerable<Service> Services
        {
            get { return _services; }
            set
            {
                if (_services != value)
                {
                    _services = value;
                    OnPropertyChanged(() => Services);
                }
            }
        }
        #endregion

        #region Property Physicians
        private IEnumerable<Employee> _physicians;
        public IEnumerable<Employee> Physicians
        {
            get { return _physicians; }
            set
            {
                if (_physicians != value)
                {
                    _physicians = value;
                    OnPropertyChanged(() => Physicians);
                }
            }
        }
        #endregion

        #region Property SelectedPostponeService
        private Service _selectedPostponeService;
        public Service SelectedPostponeService
        {
            get { return _selectedPostponeService; }
            set
            {
                if (_selectedPostponeService != value)
                {
                    _selectedPostponeService = value;
                    OnPropertyChanged(() => SelectedPostponeService);

                    GetPhysiciansInService();
                    PostponeCommand.OnCanExecuteChanged();
                }
            }
        }
        #endregion

        #region Property PostponePhysicians
        private IEnumerable<Employee> _postponePhysicians;
        public IEnumerable<Employee> PostponePhysicians
        {
            get { return _postponePhysicians; }
            set
            {
                if (_postponePhysicians != value)
                {
                    _postponePhysicians = value;
                    OnPropertyChanged(() => PostponePhysicians);
                }
            }
        }
        #endregion

        #region Property SelectedPostponePhysician
        private Employee _selectedPostponePhysician;
        public Employee SelectedPostponePhysician
        {
            get { return _selectedPostponePhysician; }
            set
            {
                if (_selectedPostponePhysician != value)
                {
                    _selectedPostponePhysician = value;
                    OnPropertyChanged(() => SelectedPostponePhysician);

                    PostponeCommand.OnCanExecuteChanged();
                }
            }
        }
        #endregion

        #region Property SelectedPostponePhysicianText
        private string _selectedPostponePhysicianText;
        public string SelectedPostponePhysicianText
        {
            get { return _selectedPostponePhysicianText; }
            set
            {
                if (_selectedPostponePhysicianText != value)
                {
                    _selectedPostponePhysicianText = value;
                    OnPropertyChanged(() => SelectedPostponePhysicianText);
                }
            }
        }
        #endregion

        #region Property SelectedPostponeDate
        private DateTime? _selectedPostponeDate;
        public DateTime? SelectedPostponeDate
        {
            get { return _selectedPostponeDate; }
            set
            {
                if (_selectedPostponeDate != value)
                {
                    _selectedPostponeDate = value;
                    OnPropertyChanged(() => SelectedPostponeDate);

                    ChangAppointmentTime();
                    PostponeCommand.OnCanExecuteChanged();
                }
            }
        }
        #endregion

        #region Property SelectedPostponeTime
        private string _selectedPostponeTime;
        public string SelectedPostponeTime
        {
            get { return _selectedPostponeTime; }
            set
            {
                if (_selectedPostponeTime != value)
                {
                    _selectedPostponeTime = value;
                    OnPropertyChanged(() => SelectedPostponeTime);
                }
            }
        }

        #endregion

        #region Property Quota 
        private int _quota;
        public int Quota
        {
            get { return _quota; }
            set
            {
                if (_quota != value)
                {
                    _quota = value;
                    OnPropertyChanged(() => Quota);
                }
            }
        }
        #endregion

        #region Propperty AppointedNumber
        private int _appointedNumber;
        public int AppointedNumber
        {
            get { return _appointedNumber; }
            set
            {
                if (_appointedNumber != value)
                {
                    _appointedNumber = value;
                    OnPropertyChanged(() => AppointedNumber);
                }
            }
        }

        #endregion

        #endregion

        #region Commands

        #region ResetCommand
        private ViewModelCommand _resetCommand = null;
        public ViewModelCommand ResetCommand
        {
            get
            {
                if (_resetCommand == null)
                    _resetCommand = new ViewModelCommand(p => Reset(p));
                return _resetCommand;
            }
        }

        private void Reset(object obj)
        {
            Reset();
        }
        #endregion

        #region PostponeCommand
        private ViewModelCommand _postponeCommand = null;
        public ViewModelCommand PostponeCommand
        {
            get
            {
                if (_postponeCommand == null)
                    _postponeCommand = new ViewModelCommand(p => Postpone(p), p => CanPostpone);
                return _postponeCommand;
            }
        }

        private void Postpone(object obj)
        {
            PostponeAppointment();
        }

        public bool CanPostpone
        {
            // comment ไว้ก่อนจะได้เหมือนๆกับ DeleteCommand
            get
            {
                return SelectedPostponeDate.HasValue &&
                       SelectedPostponePhysician != null &&
                       SelectedPostponeService != null;
            }

            //get { return true; }
        }
        #endregion

        #region DeleteCommand
        private ViewModelCommand _deleteCommand = null;
        public ViewModelCommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                    _deleteCommand = new ViewModelCommand(p => Delete(p), p => CanDelete);
                return _deleteCommand;
            }
        }

        private void Delete(object obj)
        {
            DeleteAppointments();
        }

        public bool CanDelete
        {
            get { return CanDeleteAppointment; }
        }
        #endregion

        //Daeng
        #region IsSelectedCommand
        private ViewModelCommand _isSelectedCommand = null;
        public ViewModelCommand IsSelectedCommand
        {
            get
            {
                if (_isSelectedCommand == null)
                    _isSelectedCommand = new ViewModelCommand(p => IsSelected(p));
                return _isSelectedCommand;
            }
        }

        private void IsSelected(object obj)
        {
            if (Appointments != null)
            {
                CanDeleteAppointment = Appointments.Where(p => p.IsSelected == true).Count() > 0 ? true : false;
            }
        }
        #endregion

        #endregion

        public AppointmentListViewModel(DateTime beginDate, DateTime? endDate, int? serviceID)
        {
            if (!IsInDesignModeStatic)
            {
                CalendarHelper.LoadHolidaysAndSchedules(); // ART

                BeginDate = beginDate;
                EndDate = endDate;
                ServiceID = serviceID;

                SearchAppointments();
            
                var loadBatch = new DomainContextLoadBatch(p =>
                {
                    Services = _dc.Services;
                });

                loadBatch.Add(_dc.Load(_dc.GetServicesQuery()));
                loadBatch.Add(_dc.Load(_dc.GetPhysicianSchedulesQuery()));

                Physicians = EmployeeHelper.Physicians;
                Reset();
            }
        }

        private void Reset()
        {
            //BeginDate = null;
            //EndDate = null;

            //Daeng
            if (Appointments != null)
            {
                foreach (var item in Appointments)
                    item.IsSelected = false;
            }
            IsSelected(null);

            Appointments = null;
            SelectedPostponeService = null;
            SelectedPostponeDate = null;
            SelectedPostponeTime = null;
            SelectedPostponePhysician = null;
            SelectedPostponePhysicianText = null;  
        }

        private void SearchAppointments()
        {
            // ART - deselect all previous search
            SelectAllAppointment(false);

            var qry = from p in _dc.GetAppointmentsQuery()
                      where p.AppointmentDate >= BeginDate && (EndDate != null ? p.AppointmentDate <= EndDate : true)
                      select p;

            if (ServiceID != null)
                qry = qry.Where(p => p.ServiceID == ServiceID);

            var lo = _dc.Load(qry);
            lo.Completed += (s, e) =>
            {
                Appointments = lo.Entities;
            };
        }

        private void GetPhysiciansInService()
        {
            //Daeng
            if (SelectedPostponeService != null)
                SelectedPostponeTime = SelectedPostponeService.DefaultAppointmentTime;

            ChangAppointmentTime();

            SelectedPostponePhysicianText = string.Empty;
            PostponePhysicians = _dc.PhysicianSchedules.Where(p => p.Service == SelectedPostponeService)
                                                       .Select(p => EmployeeHelper.GetPhysician(p.Physician))
                                                       .Distinct();

        }

        private void ChangAppointmentTime()
        {
            if (SelectedPostponeService != null)
            {
                if (SelectedPostponeService.ServiceID == 6) //คลีนิคนอกเวลา
                {
                    if (SelectedPostponeDate != null)
                    {
                        switch (SelectedPostponeDate.Value.DayOfWeek)
                        {
                            case DayOfWeek.Saturday:
                                SelectedPostponeTime = "8.00";
                                break;
                            case DayOfWeek.Sunday:
                                SelectedPostponeTime = "8.00";
                                break;
                            default:
                                SelectedPostponeTime = "16.00";
                                break;
                        }
                    }
                }
            }
        }


        private void PostponeAppointment()
        {
            if (Appointments == null)
            {
                MessageBox.Show("คุณยังไม่ได้ค้นหาผู้ป่วยที่ต้องการจะเลื่อนนัด");
                return;
            }

            var postponeAppointments = Appointments.Where(p => p.IsSelected);
            var newpostpone = postponeAppointments.ToList();

            if (postponeAppointments.Count() == 0)
            {
                MessageBox.Show("คุณยังไม่ได้เลือกผู้ป่วยที่ต้องการจะเลื่อนนัด");
                return;
            }

            GetAppointmentNumberAndQuota(() =>
                {
                    foreach (var appoint in postponeAppointments)
                    {
                        if (AppointedNumber < Quota)
                        {
                            var log = new LogAppointment
                            {
                                EmployeeCode = EmployeeHelper.LoggedEmployee,
                                LogDateTime = DateTime.Now,
                                Action = 5, // Postpone
                                PostponeRemark = string.Format("เลื่อนจากวัน {0:dddd} ที่ {1:d MMMM yyyy}, หน่วยบริการ: {2}, แพทย์: {3}",
                                                                appoint.AppointmentDate,
                                                                appoint.AppointmentDate,
                                                                appoint.Service.Name,
                                                                EmployeeHelper.GetPhysician(appoint.Physician)),
                                Appointment = appoint,
                            };

                            appoint.Service = SelectedPostponeService;
                            appoint.Physician = SelectedPostponePhysician.EmployeeCode;
                            appoint.AppointmentDate = SelectedPostponeDate.Value;
                            appoint.AppointmentTime = SelectedPostponeTime;

                            newpostpone.Remove(appoint);
                            AppointedNumber++;
                        }
                        else
                        {
                            break;
                        }
                    }

                    var countall = Appointments.Count();
                    if (newpostpone.Count > 0)
                    {
                        Appointments = newpostpone;
                        SelectAllAppointment(true);
                    }

                    _dc.SubmitChanges().Completed += (sender, args) =>
                    {
                        if (newpostpone.Count > 0)
                        {
                            var count = countall - newpostpone.Count;
                            MessageBox.Show(string.Format("สามารถเลื่อนคนไข้ได้จำนวน {0} ราย ยังเหลือคนไข้ {1} ราย", count, newpostpone.Count));
                        }
                        else
                        {
                            MessageBox.Show("Saved");
                            SearchAppointments();

                            //Daeng Cler Text
                            SelectedPostponeService = null;
                            SelectedPostponeDate = null;
                            SelectedPostponeTime = null;
                            SelectedPostponePhysician = null;
                            SelectedPostponePhysicianText = null;
                        }
                    };
                });

            //foreach (var appoint in postponeAppointments)
            //{
            //    var log = new LogAppointment
            //    {
            //        EmployeeCode = EmployeeHelper.LoggedEmployee,
            //        LogDateTime = DateTime.Now,
            //        Action = 5, // Postpone
            //        PostponeRemark = string.Format("เลื่อนจากวัน {0:dddd} ที่ {1:d MMMM yyyy}, หน่วยบริการ: {2}, แพทย์: {3}",
            //                                       appoint.AppointmentDate,
            //                                       appoint.AppointmentDate,
            //                                       appoint.Service.Name,
            //                                       EmployeeHelper.GetPhysician(appoint.Physician)),
            //        Appointment = appoint,
            //    };

            //    appoint.Service = SelectedPostponeService;
            //    appoint.Physician = SelectedPostponePhysician.EmployeeCode;
            //    appoint.AppointmentDate = SelectedPostponeDate.Value;
            //    appoint.AppointmentTime = SelectedPostponeTime;
            //}

            //_dc.SubmitChanges().Completed += (s, e) =>
            //{
            //    //MessageBox.Show("Saved");
            //    //SearchAppointments();
            //};
        }

        private void GetAppointmentNumberAndQuota(Action callback)
        {
            //Daeng Load Quota
            var a = _dc.PhysicianSchedules.Where(p => p.Service == SelectedPostponeService &&
                                                     p.Physician == SelectedPostponePhysician.EmployeeCode &&
                                                     p.DayOfWeek == (int)SelectedPostponeDate.Value.DayOfWeek).Where(p => p.EndDate != null ? (p.BeginDate <= SelectedPostponeDate && p.EndDate >= SelectedPostponeDate) :
                                                     (SelectedPostponeDate >= p.BeginDate));
            //Daeng
            int quota = 0;
            foreach (var item in a)
                quota = quota + item.Quota;

            Quota = quota;

            var qry = from p in _dc.GetAppointmentsQuery()
                      where p.AppointmentDate == SelectedPostponeDate &&
                            p.ServiceID == SelectedPostponeService.ServiceID &&
                            p.Physician == SelectedPostponePhysician.EmployeeCode
                      select p;

            var lo = _dc.Load(qry);
            lo.Completed += (s, e) =>
            {
                AppointedNumber = lo.Entities.Where(p => !p.AppointmentDetails.Any(o => o.PreOrderID == 16 || o.PreOrderID == 32)) // ART 16=นัดรับยา Daeng 32=นัดติดตามหลังผ่าตัด
                                             .Count();

                callback.Invoke();
            };
        }

        public void DeleteAppointments()
        {
            if (Appointments == null)
            {
                MessageBox.Show("คุณยังไม่ได้ค้นหาผู้ป่วยที่ต้องการจะยกเลิกนัด");
                return;
            }

            var postponeAppointments = Appointments.Where(p => p.IsSelected);

            if (postponeAppointments.Count() == 0)
            {
                MessageBox.Show("คุณยังไม่ได้เลือกผู้ป่วยที่ต้องการจะยกเลิกนัด");
                return;
            }

            var result = MessageBox.Show("คุณแน่ใจที่จะยกเลิกนัดเหล่านี้", "คำเตือน", MessageBoxButton.OKCancel);
            if (result == MessageBoxResult.Cancel)
                return;

            foreach (var appoint in postponeAppointments)
            {
                appoint.IsDeleted = true;

                var log = new LogAppointment
                {
                    EmployeeCode = EmployeeHelper.LoggedEmployee,
                    LogDateTime = DateTime.Now,
                    Action = 4, // Delete
                    Appointment = appoint,
                };
            }

            _dc.SubmitChanges().Completed += (s, e) =>
            {
                //MessageBox.Show("Saved");
                //SearchAppointments();
            };
        }

        public void SelectAllAppointment(bool flag)
        {
            if (Appointments == null)
                return;

            foreach (var item in Appointments)
            {
                item.IsSelected = flag;
            }
        }

        private void PrintAppointmentCard()
        {
            var vm = new AppointmentCardViewModel(SelectedAppointment);

            var window = new AppointmentCardWindow();
            window.DataContext = vm;
            window.Show();
        }

       
    }
}
